home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Halma 1.1.source Folder / Halma ƒ / Halma code ƒ / halma meat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-25  |  8.4 KB  |  299 lines  |  [TEXT/KAHL]

  1. /**********************************************************************\
  2.  
  3. File:        halma meat.c
  4.  
  5. Purpose:    This module handles all the blood and guts of Halma play;
  6.             what constitutes a valid jump, etc.
  7.  
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12.  
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with this program in a file named "GNU General Public License".
  20. If not, write to the Free Software Foundation, 675 Mass Ave,
  21. Cambridge, MA 02139, USA.
  22.  
  23. \**********************************************************************/
  24.  
  25. #include "halma meat.h"
  26. #include "halma main window.h"
  27. #include "error.h"
  28. #include "buttons.h"
  29. #include "program globals.h"
  30. #include "util.h"
  31. #include "sounds.h"
  32.  
  33. short            gStickyButtonRow, gStickyButtonColumn;
  34.  
  35. void DoValidJump(WindowDataHandle theData, short theRow, short theColumn)
  36. {
  37.     if (gThisJumpString[0]==0xFF)
  38.     {
  39.         DoSound(sound_buzz, TRUE);
  40.         HandleError(kTooManyJumpsError, FALSE);
  41.         return;
  42.     }
  43.     
  44.     Board[gStickyButtonRow][gStickyButtonColumn]=kNoPiece;
  45.     Draw3DButton(&gButtonRect[gStickyButtonRow*9+gStickyButtonColumn], 0L, 0L,
  46.         (**theData).windowDepth, FALSE);
  47.  
  48.     Board[theRow][theColumn]=kHighlightedPiece;
  49.     Draw3DButton(&gButtonRect[theRow*9+theColumn], 0L, (**theData).windowDepth>2 ?
  50.         gPieceIconColor : gPieceIconBW, (**theData).windowDepth, TRUE);
  51.     DoSound(sound_click, TRUE);
  52.     gStickyButtonRow=theRow;
  53.     gStickyButtonColumn=theColumn;
  54.     gThisJumpString[++gThisJumpString[0]]=theRow*9+theColumn+'A';
  55.     gNumJumps++;
  56.     (**theData).offscreenNeedsUpdate=TRUE;
  57. }
  58.  
  59. void DoValidFirstMove(WindowDataHandle theData, short theRow, short theColumn,
  60.     Boolean drawPiece)
  61. {
  62.     Board[theRow][theColumn]=kHighlightedPiece;
  63.     if (drawPiece)
  64.         Draw3DButton(&gButtonRect[theRow*9+theColumn], 0L, (**theData).windowDepth>2 ?
  65.             gPieceIconColor : gPieceIconBW, (**theData).windowDepth, TRUE);
  66.     gStickyButtonRow=gThisStartRow=theRow;
  67.     gStickyButtonColumn=gThisStartColumn=theColumn;
  68.     (**theData).offscreenNeedsUpdate=TRUE;
  69.     gNumJumps=0;
  70.     gThisJumpString[0]=0x01;
  71.     gThisJumpString[1]='A'+theRow*9+theColumn;
  72. }
  73.  
  74. void DoValidSingleMove(WindowDataHandle theData, short theRow, short theColumn)
  75. {
  76.     DoValidJump(theData, theRow, theColumn);
  77.     SaveJumpChain();
  78.     DoValidFirstMove(theData, theRow, theColumn, FALSE);
  79.     DrawScoreAndStuff(theData, (**theData).windowDepth);
  80. }
  81.  
  82. void DoValidSingleMoveNewMove(WindowDataHandle theData, short theRow, short theColumn)
  83. {
  84.     SaveJumpChain();
  85.     DoValidFirstMove(theData, gStickyButtonRow, gStickyButtonColumn, FALSE);
  86.     DoValidSingleMove(theData, theRow, theColumn);
  87. }
  88.  
  89. void DoOffBoard(WindowDataHandle theData)
  90. {
  91.     if ((gStickyButtonRow!=-1) && (gStickyButtonColumn!=-1))
  92.         DoAlreadyHighlighted(theData, gStickyButtonRow, gStickyButtonColumn);
  93. }
  94.  
  95. void DoCantJumpThere(WindowDataHandle theData)
  96. {
  97.     DoSound(sound_buzz, TRUE);
  98.     HandleError(kCantGetThereFromHereError, FALSE);
  99. }
  100.  
  101. void DoMustJumpOverPiece(WindowDataHandle theData)
  102. {
  103.     DoSound(sound_buzz, TRUE);
  104.     HandleError(kJumpOverNonPieceError, FALSE);
  105. }
  106.  
  107. void DoCantSelectNonPiece(WindowDataHandle theData)
  108. {
  109.     DoSound(sound_buzz, TRUE);
  110.     HandleError(kNonPieceError, FALSE);
  111. }
  112.  
  113. void DoSpaceNotEmpty(WindowDataHandle theData, short theRow, short theColumn)
  114. {
  115.     DoAlreadyHighlighted(theData, gStickyButtonRow, gStickyButtonColumn);
  116.     DoValidFirstMove(theData, theRow, theColumn, TRUE);
  117. }
  118.  
  119. void DoAlreadyHighlighted(WindowDataHandle theData, short theRow, short theColumn)
  120. {
  121.     Board[theRow][theColumn]=kPiece;
  122.     Draw3DButton(&gButtonRect[theRow*9+theColumn], 0L, 
  123.         (**theData).windowDepth>2 ? gPieceIconColor : gPieceIconBW,
  124.         (**theData).windowDepth, FALSE);
  125.     gStickyButtonRow=gStickyButtonColumn=-1;
  126.  
  127.     if (((theRow!=gThisStartRow) || (theColumn!=gThisStartColumn)) && (gNumJumps>0))
  128.         SaveJumpChain();
  129.     
  130.     gNumJumps=0;
  131.     gThisJumpString[0]=0x00;
  132.     DrawScoreAndStuff(theData, (**theData).windowDepth);
  133. }
  134.  
  135. enum MoveTypes GetMoveType(short theRow, short theColumn)
  136. {
  137.     short            hdif, vdif;
  138.     short            vave, have;
  139.     
  140.     if ((theRow<0) || (theRow>=gNumRows) || (theColumn<0) || (theColumn>=gNumColumns))
  141.         return kOffBoard;
  142.     
  143.     if ((gStickyButtonRow==-1) && (gStickyButtonColumn==-1))
  144.         return (Board[theRow][theColumn]==kPiece) ? kValidFirstMove : kCantSelectNonPiece;
  145.     
  146.     if ((theRow==gStickyButtonRow) && (theColumn==gStickyButtonColumn))
  147.         return kAlreadyHighlighted;
  148.     
  149.     if (Board[theRow][theColumn]!=kNoPiece)
  150.         return kSpaceNotEmpty;
  151.     
  152.     vdif=theRow-gStickyButtonRow;
  153.     if (vdif<0) vdif=-vdif;
  154.     hdif=theColumn-gStickyButtonColumn;
  155.     if (hdif<0) hdif=-hdif;
  156.  
  157.     if (((vdif==2) && (hdif==2)) || ((vdif==2) && (hdif==0)) ||
  158.         ((vdif==0) && (hdif==2)))
  159.     {
  160.         vave=(theRow+gStickyButtonRow)/2;
  161.         have=(theColumn+gStickyButtonColumn)/2;
  162.         return (Board[vave][have]==kPiece) ? kValidJump : kMustJumpOverPiece;
  163.     }
  164.     else if ((vdif==1) && (hdif==1) || (vdif==1) && (hdif==0) ||
  165.             (vdif==0) && (hdif==1))
  166.         return (gNumJumps==0) ? kValidSingleMove : kValidSingleMoveNewMove;
  167.     else
  168.         return kCantJumpThere;
  169. }
  170.  
  171. void SaveJumpChain(void)
  172. {
  173.     unsigned long        theSize;
  174.     
  175.     theSize=GetHandleSize((Handle)gTheFullJumpHandle);
  176.     SetHandleSize((Handle)gTheFullJumpHandle, theSize+gThisJumpString[0]+1);
  177.     Mymemcpy((Ptr)(*gTheFullJumpHandle+gThisJumpString[0]+1), (Ptr)(*gTheFullJumpHandle),
  178.         theSize);
  179.     Mymemcpy((Ptr)(*gTheFullJumpHandle), (Ptr)gThisJumpString, gThisJumpString[0]+1);
  180.     gThisJumpString[0]=0x00;
  181.     gNumJumps=0;
  182.     gNumMoves++;
  183. }
  184.  
  185. void UndoOneJump(WindowDataHandle theData)
  186. {
  187.     unsigned char    thisChar;
  188.     short            theRow, theColumn;
  189.     
  190.     if (gThisJumpString[0]>0x01)    /* back up one in jump chain */
  191.     {
  192.         Board[gStickyButtonRow][gStickyButtonColumn]=kNoPiece;
  193.         Draw3DButton(&gButtonRect[gStickyButtonRow*9+gStickyButtonColumn], 0L, 0L,
  194.             (**theData).windowDepth, FALSE);
  195.         gThisJumpString[0]--;
  196.         gNumJumps--;
  197.         thisChar=gThisJumpString[gThisJumpString[0]]-'A';
  198.         gStickyButtonColumn=theColumn=thisChar%9;
  199.         gStickyButtonRow=theRow=(thisChar-theColumn)/9;
  200.         Board[theRow][theColumn]=kHighlightedPiece;
  201.         Draw3DButton(&gButtonRect[theRow*9+theColumn], 0L, (**theData).windowDepth>2 ?
  202.             gPieceIconColor : gPieceIconBW, (**theData).windowDepth, TRUE);
  203.         DoSound(sound_click, TRUE);
  204.     }
  205.     else    /* piece highlighted but no jumps yet --> no piece highlighted */
  206.     {
  207.         Board[gStickyButtonRow][gStickyButtonColumn]=kPiece;
  208.         Draw3DButton(&gButtonRect[gStickyButtonRow*9+gStickyButtonColumn], 0L, 
  209.             (**theData).windowDepth>2 ? gPieceIconColor : gPieceIconBW,
  210.             (**theData).windowDepth, FALSE);
  211.         gStickyButtonRow=gStickyButtonColumn=-1;
  212.         gThisJumpString[0]=0x00;
  213.     }
  214.     
  215.     DrawScoreAndStuff(theData, (**theData).windowDepth);
  216. }
  217.  
  218. void UndoWholeMove(WindowDataHandle theData)
  219. {
  220.     unsigned char    lengthOfLastJump;
  221.     unsigned long    newFullJumpHandleLength;
  222.     unsigned char    thisChar;
  223.     
  224.     lengthOfLastJump=**gTheFullJumpHandle;
  225.     newFullJumpHandleLength=GetHandleSize((Handle)gTheFullJumpHandle)-lengthOfLastJump-1;
  226.     Mymemcpy((Ptr)gThisJumpString, (Ptr)(*gTheFullJumpHandle), lengthOfLastJump+1);
  227.     Mymemcpy((Ptr)*gTheFullJumpHandle, (Ptr)*gTheFullJumpHandle+lengthOfLastJump+1,
  228.         newFullJumpHandleLength);
  229.     SetHandleSize((Handle)gTheFullJumpHandle, newFullJumpHandleLength);
  230.     gNumJumps=gThisJumpString[0]-1;
  231.     gNumMoves--;
  232.     thisChar=gThisJumpString[gThisJumpString[0]]-'A';
  233.     gStickyButtonColumn=thisChar%9;
  234.     gStickyButtonRow=(thisChar-gStickyButtonColumn)/9;
  235.     UndoOneJump(theData);
  236. }
  237.  
  238. short BestSolution(void)
  239. {
  240. // this could be compressed a lot, but it's in this expanded for readability
  241.     switch (gNumRows)
  242.     {
  243.         case 4:
  244.             switch (gNumColumns)
  245.             {
  246.                 case 4:        return 6;
  247.                 case 5:        return 8;
  248.                 case 6:        return 10;
  249.                 case 7:        return 12;
  250.                 case 8:        return 16;
  251.                 default:    return 0;
  252.             }
  253.             break;
  254.         case 5:
  255.             switch (gNumColumns)
  256.             {
  257.                 case 4:        return 8;
  258.                 case 5:        return 9;
  259.                 case 6:        return 12;
  260.                 default:    return 0;
  261.             }
  262.             break;
  263.         case 6:
  264.             switch (gNumColumns)
  265.             {
  266.                 case 4:        return 10;
  267.                 case 5:        return 12;
  268.                 case 6:        return 12;
  269.                 default:    return 0;
  270.             }
  271.             break;
  272.         case 7:
  273.             switch (gNumColumns)
  274.             {
  275.                 case 4:        return 12;
  276.                 case 7:        return 13;
  277.                 default:    return 0;
  278.             }
  279.             break;
  280.         case 8:
  281.             switch (gNumColumns)
  282.             {
  283.                 case 4:        return 16;
  284.                 case 8:        return 15;
  285.                 default:    return 0;
  286.             }
  287.             break;
  288.         case 9:
  289.             switch (gNumColumns)
  290.             {
  291.                 case 9:        return 16;
  292.                 default:    return 0;
  293.             }
  294.             break;
  295.     }
  296.     
  297.     return 0;
  298. }
  299.